﻿#include "NPPPySidePlugin.h"
#include <string>

static const wchar_t *Plugin_Name = L"NPPPySide";

typedef void (__cdecl * SetInfo)(NppData);
typedef FuncItem * (__cdecl * GetFuncsArray)(int *);
typedef void (__cdecl * BeNotified)(SCNotification *);
typedef LRESULT (__cdecl * MessageProc)(UINT, WPARAM, LPARAM);

static SetInfo __setInfo = nullptr;
static GetFuncsArray __getFuncsArray = nullptr;
static BeNotified __beNotified = nullptr;
static MessageProc __messageProc = nullptr;

void setInfo(NppData notpadPlusData)
{
    if (__setInfo == nullptr) {
        HMODULE module = nullptr;
        wchar_t temp[256] = {0};
        void *funcAddr = reinterpret_cast<void*>(setInfo);
        if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<wchar_t*>(funcAddr), &module))
        {
            GetModuleFileName(module, temp, 256);
            std::wstring currentPluginPath(temp);
            size_t index = currentPluginPath.find_last_of(L'\\');
            currentPluginPath = currentPluginPath.substr(0, index);
            std::wstring pathEnvNow(_wgetenv(L"path"));
            std::wstring pysidePath = currentPluginPath + L"\\Lib\\site-packages\\PySide2";

            pathEnvNow = L"PATH=" + pathEnvNow + L";" + currentPluginPath + L";" + pysidePath;
            _wputenv(pathEnvNow.data());

            wchar_t curpath[256] = {0};
            GetCurrentDirectoryW(256, curpath);

            SetCurrentDirectoryW(currentPluginPath.data());

            HMODULE hm = LoadLibraryW(L"NPPPySideQt.dll");
            if (hm == nullptr)
                return;

            __setInfo = reinterpret_cast<SetInfo>(GetProcAddress(hm, "_setInfo"));
            __getFuncsArray = reinterpret_cast<GetFuncsArray>(GetProcAddress(hm, "_getFuncsArray"));
            __beNotified = reinterpret_cast<BeNotified>(GetProcAddress(hm, "_beNotified"));
            __messageProc = reinterpret_cast<MessageProc>(GetProcAddress(hm, "_messageProc"));

            SetCurrentDirectoryW(curpath);
        }
    }

    if (__setInfo == nullptr)
        return;
    __setInfo(notpadPlusData);
}

const wchar_t * getName()
{
    return Plugin_Name;
}

FuncItem *getFuncsArray(int *nbF)
{
    if (__getFuncsArray == nullptr)
        return nullptr;
    return __getFuncsArray(nbF);
}


void beNotified(SCNotification *notifyCode)
{
    if (__beNotified == nullptr)
        return;
    __beNotified(notifyCode);
}


LRESULT messageProc(UINT m, WPARAM w, LPARAM l)
{
   if (__messageProc == nullptr)
       return FALSE;
   return __messageProc(m, w, l);
}


BOOL isUnicode()
{
    return TRUE;
}


